<?php
import("com.mysql.yado.MysqlDriver");
import("com.miho.config.Config");
import("com.miho.io.Request");
import("com.yamvc.controller.Controller");
import("com.yamvc.view.View");
import("com.yamvc.model.Model");
import("com.yamvc.application.events.ApplicationEvent");
import("com.yamvc.application.users.User");
import("com.yamvc.ClassNotFoundException");
import("com.miho.logger.Logger");
Logger::getLogger("Application")->setLevel(Logger::ERROR_LEVEL);
class Application {
	const AJAX_ON="ajaxOn";
	const AJAX_OFF="ajaxOff";
	private $_actionsNameSpace="com.simpleApplication.actions";
	public function getActionNamespace(){
		return $this->_actionsNameSpace;
	}
	private $_eventsNameSpace="com.simpleApplication.events";
	public function getEventsNameSpace(){
		return $this->_eventsNameSpace;
	}
	private $_path;
	/// defaults
	private $_defaultActionClass="DefaultAction";
	private $_pageNotFoundAction="PageNotFoundAction";
	private $_rendererClass="com.PHPTemplater.Engine";
	private $_templatesDirName="tpl";
	private $_templatesBaseDir;	
	private $_baseDir="http://127.0.0.1:8081/";
	public function getBaseDir(){
		return $this->_baseDir;
	}
	private $_useAjax=Application::AJAX_OFF;
	public function useAjax(){
		return $this->_useAjax;
	}
	
	private $_scriptBasePath="http://127.0.0.1:8081/js/";
	public function getScriptPath(){
		return $this->_scriptBasePath;
	}
	private $_imagesBasePath="http://localhost:8081/assets/";
	public function getImagesPath(){
		return $this->_imagesBasePath;
	}
	private $_stylesBasePath="http://172.17.17.15:82/css/";
	public function getstylesPath(){
		return $this->_stylesBasePath;
	}
	/**
	 * Enter description here...
	 *
	 * @var Config
	 */
	private $_conf;
	private $_user;
	
	
	/**
	 * Enter description here...
	 *
	 * @var Application
	 */
	private static $_appInstance;
	/**
	 * Enter description here...
	 *
	 * @return Application
	 */
	public static function getAppInstance(){
		return self::$_appInstance;
	}
	
	public static function create($path){
		self::$_appInstance=null;
		if (is_dir($path)&&is_dir($path."/conf")){
			self::$_appInstance = new Application($path);
			self::$_appInstance->init();
			self::$_appInstance->initRenderer();
			self::$_appInstance->registerProxyes();
			self::$_appInstance->registerTemplates();
			self::$_appInstance->registerMediators();
			self::$_appInstance->dispatchAction();
			self::$_appInstance->dispatchEvent();
			Controller::instance()->dispatchEvent(new ApplicationEvent(ApplicationEvent::PRERENDER,self::$_appInstance));
			View::instance()->render();
			return;
		}
		// TODO throw exception
	}
	private $_configPath;
	protected function __construct($path){
		$this->_configPath = $path."/conf/";
		$this->_conf = Config::getConfig($this->_configPath."config.xml");
		$this->_templatesBaseDir = $path."/".$this->_templatesDirName;
	}
	/**
	 * Enter description here...
	 *
	 * @return Config
	 */
	public function getConfig(){
		return $this->_conf;
	}
	/**
	 * Enter description here...
	 *
	 * @return User
	 */
	public function getUser(){
		return $this->_user;
	}
	protected function init(){
		if(isset($_SERVER["HTTP_X_REQUESTED_WITH"])){
			if($_SERVER["HTTP_X_REQUESTED_WITH"]=="XMLHttpRequest"){
				echo "!";
				exit();
			}
		}
		$this->_useAjax = $this->_conf->get("com.application.useAjax",self::AJAX_OFF);
		$this->_defaultAction = $this->_conf->get("config.application.defaultActionClass",$this->_defaultActionClass);
		$this->_actionsNameSpace = $this->_conf->get("config.application.actionsNameSpace",$this->_actionsNameSpace);
		$this->_eventsNameSpace = $this->_conf->get("config.application.actionsNameSpace",$this->_eventsNameSpace);
		$this->_baseDir = $this->_conf->get("config.application.baseDir",$this->_baseDir);
		$this->_scriptBasePath= $this->_conf->get("config.application.scriptPath",$this->_scriptBasePath);
		$this->_imagesBasePath= $this->_conf->get("config.application.imagesPath",$this->_imagesBasePath);
		$this->_stylesBasePath= $this->_conf->get("config.application.stylesPath",$this->_stylesBasePath);
		$this->_rendererClass = $this->_conf->get("config.view.rendererClass",$this->_rendererClass);
		$this->_templatesDirName = $this->_conf->get("config.render.templatesDirName",$this->_templatesDirName);
		Controller::instance()->dispatchEvent(new ApplicationEvent(ApplicationEvent::INITALIZE,$this));
	}
	
	protected function registerTemplates(){
		$templates = $this->_conf->getElement("config.view.templates.template");
		View::instance()->createRootTemplate($this->_conf->get("config.view.rootTemplate","index")); 
		View::instance()->registerTemplates($templates);
	}
	
	protected function registerProxyes(){
		$proxyes = $this->_conf->getElement("config.model.proxyes.proxy");
		Model::instance()->registerProxyes($proxyes);
	}
	
	protected function registerMediators(){
		$mediators = $this->_conf->getElement("config.view.mediators.mediator");
		View::instance()->registerMediators($mediators);
	}
	
	protected function initRenderer(){
		try{
			import($this->_rendererClass);
			$engine = new Engine();
			View::instance()->setRenderer($engine)->setBasePath($this->_templatesBaseDir);
			//if ($this->_userAjax==self::AJAX_ON){
				$engine->addScript("prototype");
			//}
			
		}catch (Exception $e){
			echo "FATAL! Rendering engine load failrue";
			throw $e;
			//exit();
		}
	}
	
	private $_currentAction;
	public function getCurrentAction(){
		return $this->_currentAction;
	}
	
	protected function dispatchAction(){
		try{
			$actionClass = Request::instance()->get->action;
		}catch (NullPointerException $e){
			$actionClass = $this->_defaultActionClass;
		}
		try{
			import($this->_actionsNameSpace.".".$actionClass);
		}catch (ClassNotFoundException $e){
			//throw $e;
			$actionClass = $this->_pageNotFoundAction;
			import($this->_actionsNameSpace.".".$actionClass);
		}
		try{
			$actionConf = Config::getConfig($this->_configPath.$actionClass.".xml");
			if($actionConf->get("action.view.rootTemplate")!==null){
				View::instance()->createRootTemplate($actionConf->get("action.view.rootTemplate"));	
			}
		}catch (Exception $e){
			$actionConf=null;
		}
		$action = new $actionClass($actionConf);
		if($action instanceof IAction){
			Controller::instance()->executeAction($action);	
		}
		$this->_currentAction = $actionClass;
		$this->_user=User::getActiveUser();
		Controller::instance()->dispatchEvent(new ApplicationEvent(ApplicationEvent::ACTION_DISPATCHED,$this));
	}
	private $_eventReceaved = false;
	public function eventReceaved(){
		return $this->_eventReceaved;
	}
	public function dispatchEvent(){
		try{
			$event = Request::instance()->get->eventName;
			//$this->parseEventString($event);
			$this->parseEvent();
		}catch (NullPointerException $e){
			//do nothig. there is no eny event
			Controller::instance()->dispatchEvent(new ApplicationEvent(ApplicationEvent::DEFAULT_EVENT,$this));
		}
		Controller::instance()->dispatchEvent(new ApplicationEvent(ApplicationEvent::EVENT_DISPATCHED,$this));
	}
	
	//example string MenuEvent:ITEM_CLICK(blog)
	protected function parseEvent(){
		try{
			$eventClass = Request::instance()->get->eventName;
			$eventType = Request::instance()->get->eventType;
			import($this->_eventsNameSpace.".".$eventClass);
			$event = new $eventClass($eventType,Request::instance()->get->eventParams);
			Controller::instance()->dispatchEvent($event);
			$this->_eventReceaved=true;
		}catch (Exception $e){
			//echo $e->getMessage();
			Controller::instance()->dispatchEvent(new ApplicationEvent(ApplicationEvent::DEFAULT_EVENT,$this));
			return;
		}
	}
	
	protected function parseEventString($string){
		$eventClass = explode(":",$string);
		if(!isset($eventClass[1])) return;
		$eventType=$eventClass[1];
		$eventClass = $eventClass[0];
		$eventType = explode("(",$eventType);
		if(!isset($eventType[1])) return;
		$params = explode(",",str_replace(")","",$eventType[1]));
		$eventType=$eventType[0];
		try{
			import($this->_eventsNameSpace.".".$eventClass);
			$event = new $eventClass($eventType,$params);
			Controller::instance()->dispatchEvent($event);
			$this->_eventReceaved=true;
		}catch (Exception $e){
			Controller::instance()->dispatchEvent(new ApplicationEvent(ApplicationEvent::DEFAULT_EVENT,$this));
			return;
		}
	}
}

?>